package com.components.base.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.ScreenUtils;
import com.components.base.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 跑马灯效果 TextView
 */

public class MarqueeView extends androidx.appcompat.widget.AppCompatTextView implements Runnable, View.OnClickListener {
    private String showingTextViewString;//最终绘制的文本
    private int textColor = Color.BLACK;//文字颜色,默认黑色
    private float textSize = 14;//文字颜色,默认黑色

    private float startLocationDistance = 0F;//开始的位置选取，百分比来的，距离左边，0~1，0代表不间距，1的话代表，从右面，1/2代表中间。

    private boolean isResetLocation = true;//默认为true
    private float xLocation = 0;//文本的x坐标
    private int contentWidth;//内容的宽度

    public boolean isRoll = false;//是否继续滚动

    private TextPaint paint;//画笔
    private Rect rect;

    private boolean resetInit = true;

    private Thread thread;
    private String content = "";

    private float textHeight;

    private int mBlankSpace = 10;//文本后面添加10个单位的空格，保证最后一个字或者符号全部展示出来
    /**
     * 上下文  用于滚的动画使用
     */
    private Context mContext;

    /**
     * 当前点击文本下标
     */
    private int currentTextPosition = -1;

    /**
     * 当前数据下标
     */
    private int mCurrentIndex = 0;

    /**
     * 数据源
     */
    private List<String> mData = new ArrayList<>();

    private TextRecordState mTextRecordState;

    public void setTextRecordStateInterface(TextRecordState textRecordState) {
        mTextRecordState = textRecordState;
    }

    /**
     * 需要抛出对应Item位置的点击事件
     */
    private ItemClick mItemClick;

    public void setItemClick(ItemClick itemClick) {
        mItemClick = itemClick;
    }

    public MarqueeView(Context context) {
        this(context, null);
    }

    public MarqueeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MarqueeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        setAttr();
        initPaint();
    }

    /**
     * 刻字机修改
     */
    private void initPaint() {
        rect = new Rect();
        paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);//初始化文本画笔
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(textColor);//文字颜色值,可以不设定
        paint.setTextSize(ConvertUtils.dp2px(textSize));//文字大小
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (resetInit) {
            if (startLocationDistance < 0) {
                startLocationDistance = 0;
            } else if (startLocationDistance > 1) {
                startLocationDistance = 1;
            }
            xLocation = getWidth() * startLocationDistance;
            resetInit = false;
        }
        if (contentWidth + (int) xLocation < getWidth()) {//当滚动文本额小于屏幕宽度的时候，终止滚动
            stopRoll();
        }
        //把文字画出来
        if (showingTextViewString != null) {
            canvas.drawText(showingTextViewString, xLocation, getHeight() / 2 + textHeight / 2, paint);
        }
    }

    @Override
    public void run() {
        while (isRoll && !TextUtils.isEmpty(content)) {
            try {
                Thread.sleep(12);
                xLocation = xLocation - 1;
                postInvalidate();//每隔10毫秒重绘视图
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 继续滚动
     */
    public void continueRoll() {
        if (!isRoll) {
            if (thread != null) {
                thread.interrupt();
                thread = null;
            }
            isRoll = true;
            thread = new Thread(this);
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    thread.start();//开启死循环线程让文字动起来
                }
            }, 1000); // 延时1秒
        }
    }

    /**
     * 停止滚动
     * isOverScreen 文本字段是否超出屏幕范围
     */
    public void stopRoll() {
        isRoll = false;
        if (thread != null) {
            thread.interrupt();
            thread = null;
        }
        mTextRecordState.waitOver();
    }

    private float getContentWidth(String black) {
        if (black == null || black == "") {
            return 0;
        }
        if (rect == null) {
            rect = new Rect();
        }
        paint.getTextBounds(black, 0, black.length(), rect);
        textHeight = getContentHeight();
        return rect.width();
    }

    /**
     * 获取文本高度，这里自己算的才能勉强达到google工程师TextView正常显示的
     * google工程师yysd class
     *
     * @param
     * @return
     */
    private float getContentHeight() {
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        return Math.abs((fontMetrics.bottom - fontMetrics.top)) / 2;
    }

    /**
     * |设置滚动的条目内容 ， 集合形式的
     *
     * @param strings
     */
    public void setContent(ArrayList<String> strings) {
        mData = strings;
        if (mData.size() > 0) {
            nextMove();
        }
    }

    /**
     * 滚起来吧 baby
     */
    public void nextMove() {
        setTextAnimationOut();
        mSwitchHandler.postDelayed(() -> {
            currentTextPosition = mCurrentIndex % mData.size();
            mCurrentIndex++;
            setTextAnimationIn();
            setContent(mData.get(currentTextPosition));
            invalidate();
        }, 1000);
    }

    public final Handler mSwitchHandler = new Handler(Looper.myLooper() != null ? Looper.myLooper() : Looper.getMainLooper());

    /**
     * 滚进来的动画
     */
    private void setTextAnimationIn() {
        Animation scaleIn = AnimationUtils.loadAnimation(mContext, R.anim.window_down_up_in);
        scaleIn.setDuration(200);
        scaleIn.setFillAfter(true);
        startAnimation(scaleIn);
    }

    /**
     * 滚出去的动画
     */
    private void setTextAnimationOut() {
        Animation scaleOut = AnimationUtils.loadAnimation(mContext, R.anim.window_down_up_out);
        scaleOut.setDuration(1000);
        scaleOut.setFillAfter(true);
        startAnimation(scaleOut);
    }

    /**
     * 设置滚动的条目内容  字符串形式的
     */
    public void setContent(String content2) {
        if (TextUtils.isEmpty(content2)) {
            return;
        }
        if (isResetLocation) {//控制重新设置文本内容的时候，是否初始化xLocation。
            xLocation = getWidth() * startLocationDistance;
        }
        this.content = content2;
        //这里需要计算宽度
        //如果说是循环的话，则需要计算 文本的宽度 ，然后再根据屏幕宽度 ， 看能一个屏幕能盛得下几个文本
        contentWidth = (int) (getContentWidth(content)) + mBlankSpace;//可以理解为一个单元内容的长度(加10防止强转时候丢弃的小数点部分)
        this.showingTextViewString = "";
        if (contentWidth < ScreenUtils.getAppScreenWidth()) {//如果没有超出屏幕，则不滚动
            stopRoll();
        }
        this.showingTextViewString = this.content;
        if (!isRoll && contentWidth > ScreenUtils.getAppScreenWidth()) {//如果没有在滚动的话，重新开启线程滚动
            continueRoll();
        }
    }

    /**
     * 始终获取焦点
     * 跑马灯在TextView处于焦点状态的时候才会滚动
     */
    @Override
    public boolean isFocused() {
        return true;
    }

    /**
     * 设置相关属性
     */
    private void setAttr() {
        this.setEllipsize(TextUtils.TruncateAt.MARQUEE); //设置跑马灯效果
        this.setMarqueeRepeatLimit(1); //设置跑马灯重复次数
        this.setSingleLine(); //设置单行
        this.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        mItemClick.click(currentTextPosition);
    }

    /**
     * 记录文本变化状态
     * 主要是用来记录是否超出屏幕和等待大家一起翻滚吧
     */
    public interface TextRecordState {
        /**
         * 告知文本已经滚动结束，可以开始下一次翻滚
         */
        void waitOver();
    }

    public interface ItemClick {
        /**
         * 带item位置的点击事件
         */
        void click(int position);
    }
}
